#!/usr/bin/perl

# Reads /proc/bus/usb/devices and selectively lists and/or
# interprets it.
#
# quoted from <http://lwn.net/2000/0106/a/usbproc.html>

$DEVFILENAME = "/proc/bus/pci/devices";
$PROGNAME = $0;

print "\n";

$TAGS = $ARGV[0];       # save user TAGS
if (length ($TAGS) == 0)
{
}

if (! open (DEVNUM, "<$DEVFILENAME"))
{
    print "$PROGNAME: cannot open '$DEVFILENAME'\n";
    exit 1;
}

while ($line = <DEVNUM>)    # read a text line from DEVNUM
{
    # skip all lines except those that begin with "T:" or "D:" or "I:".
    if (($line !~ "^T:") && ($line !~ "^I:") && ($line !~ "^D:"))
    {
        next;   # to the next line
    }

    chomp $line;        # remove line endings

    # First convert '=' signs to spaces.
    $line =~ tr/=/ /;

    # and convert all '(' and ')' to spaces.
    $line =~ tr/(/ /;
    $line =~ tr/)/ /;

    # split the line at spaces.
    @fields = split / +/, $line;

    if ($line =~ "^T:")
    {
        # split yields: $bus, $level, $port, $devnum, $speed, $maxchild.

        $bus    = @fields [2];
        $level  = @fields [4];
        $port   = @fields [8];
        $devnum = @fields [12];
        $speed  = @fields [14];
        $maxchild = @fields [16];
        $devclass = "?";
        $intclass = "?";
        $driver   = "?";
        $ifnum    = "?";
        $showclass = "?";   # derived from $devclass or $intclass
        next;
    } # end T: line
    elsif ($line =~ "^D:")
    { # for D: line
        $devclass = @fields [5];
        next;
    }
    else
    { # for I: line
        $intclass = @fields [9];
        $ifnum    = @fields [2];
        $driver   = @fields [15];
    } # end I: line

    if ($level > 1)
    {
        $temp = $level;
        while ($temp > 1)
        {
            print "    ";
            $temp--;
        }
    }

    if (($devclass eq ">ifc") || ($devclass eq "unk."))
    {   # then use InterfaceClass, not DeviceClass
        $showclass = $intclass;
    }
    else
    {   # use DeviceClass
        $showclass = $devclass;
    }

    if ($level == 0)
    {
        print sprintf ("/:  Bus $bus.Port $port: Dev $devnum, Class=root_hub, Driver=hub/%sp, %sM\n",
            $maxchild, $speed);
    }
    else
    {
        print sprintf ("|__ Bus $bus.Port $port: Dev $devnum, If $ifnum, Class=$showclass, Driver=$driver%s, %sM\n",
            ($maxchild == 0) ? "" : ("/" . $maxchild . "p"),
            $speed);
    }
} # end while DEVNUM

close (DEVNUM);
print "\n";

# END.
